feat: well_manager + well estimator#3972
Conversation
…aint class hierachy , 3) Remove all old constraint handling methods/variables, 4) it compiles ...
…lephase still needs testing
…t compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml
… to fixed and inputFiles regenerated
…d convert compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml" This reverts commit fa61ab1.
…well initialization vagaries assoiated with useSurfaceConditions=0
…for resvol constraint, compositional only
| // set the reference well element where the BHP control is applied | ||
| wellControls.setReferenceGravityCoef( refElev * gravVector[2] ); | ||
| wellControls.setReferenceGravityCoef( refElev * gravVector[2] ); // tjb remove |
There was a problem hiding this comment.
Removed and setup access to bhp constraint value. The pattern could be improved but in a different PR.
| // 13.4) Make sure there is at least one non-BHP constraint | ||
| bool const rate_match_found = std::any_of( constraints.begin(), constraints.end(), [&bhp_type]( const auto & constraint_tuple ) | ||
| { | ||
| return std::get< 1 >( constraint_tuple ) != bhp_type; | ||
| } ); | ||
| GEOS_THROW_IF( !rate_match_found, | ||
| GEOS_FMT( "Missing rate constraint for {} well {}", | ||
| (isProducerWell ? "producer" : "injector"), getName() ), |
There was a problem hiding this comment.
if a well has phaseVolRate while defining only a total-volume rate constraint, this check would flag things are good, but i guess initialization would hit issues later.
There was a problem hiding this comment.
not sure about the distinction between has phaseVolRate and defining a totalVolrate... its just verifying if a rate constraint is present... current code needs 1 bhp and at least 1 rate constraint ... error checking on a specific type is done in constraint object
| string const bhp_type = isProducerWell ? MinimumBHPConstraint::catalogName() : MaximumBHPConstraint::catalogName(); | ||
| bool const no_match_found = std::none_of( constraints.begin(), constraints.end(), [&bhp_type]( const auto & constraint_tuple ) | ||
| { | ||
| return std::get< 1 >( constraint_tuple ) == bhp_type; | ||
| } ); | ||
| GEOS_THROW_IF( no_match_found, |
There was a problem hiding this comment.
When the sole BHP or rate constraint has constraintActive=0, these existence checks still accept it, while getBHPConstraint and the rate-list helpers filter it out. Subsequent selection either dereferences null or erases an end() iterator because the current constraint is absent from the active list.
There was a problem hiding this comment.
Not sure if this address your comment... for all current models constraintActive = 1. The addition of this flag was needed for 2 workflows, wellheadpressure, where the simulator can impose an "internal constraint" and the underpinning of future functionality where a well can be assigned producer and injection constraints, which then come into consideration when only the well type changes, versus the need to define 2 wells with same perforation information. For either the code will need to ensure that an active pressure and rate constraint are present.
| * @param domain the physical domain object | ||
| */ | ||
| void chopNegativeDensities( DomainPartition & domain ); | ||
| #if 0 |
| m_useMass( false ), | ||
| m_useTotalMassEquation( 1 ), | ||
| m_isThermal( 0 ), | ||
| m_isCompositional( true ), |
There was a problem hiding this comment.
should'nt it be an integer and registered for restart ? what happen if we want to restard a non-compositional well ?
There was a problem hiding this comment.
The variable is an internal flag set for initial and restart runs. I'm guessing the integratedTests would fail if it was set for restarts.
| array1d< real64 > localResidualNorm, wellResidalNorm; | ||
| array1d< real64 > localResidualNormalizer; | ||
|
|
||
| if( isThermal() ) |
There was a problem hiding this comment.
Sticking to conventionm shouldn't it be set by NDOF or so ?
There was a problem hiding this comment.
Yes, it would add the volume balance.. I will create a separate PR so any changes are associated with a specific change.
| if( wellResidalNorm[i] > localResidualNorm[i] ) | ||
| { | ||
| localResidualNorm[i] = wellResidalNorm[i]; | ||
| } |
There was a problem hiding this comment.
| if( wellResidalNorm[i] > localResidualNorm[i] ) | |
| { | |
| localResidualNorm[i] = wellResidalNorm[i]; | |
| } | |
| localResidualNorm[i] = LvArray::math::max( localResidualNorm[i], wellResidualNorm[i] ); |
| // step 1: compute the norm in the subRegion | ||
| if( wellControls.isWellOpen( ) ) | ||
| { | ||
| wellResidalNorm = wellControls.calculateLocalWellResidualNorm( time_n, |
There was a problem hiding this comment.
| wellResidalNorm = wellControls.calculateLocalWellResidualNorm( time_n, | |
| wellResidualNorm = wellControls.calculateLocalWellResidualNorm( time_n, |
jhuang2601
left a comment
There was a problem hiding this comment.
@tjb-ltk Great job!
Please update the branch with latest develop repo, which will fix the following failures for readthedoc build:
WARNING: Error, no command xref target from index:QuickStart
WARNING: Error, no command xref target from index:Tutorials
WARNING: Error, no command xref target from index:BasicExamples
WARNING: Error, no command xref target from index:AdvancedExamples
WARNING: Error, no command xref target from index:UserGuide
| // setup fluid model | ||
| string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); | ||
| constitutive::MultiFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::MultiFluidBase >( fluidName ); | ||
| std::cout << "Validating fluid model for well " << getName() << "..." << m_useMass << std::endl; |
There was a problem hiding this comment.
| std::cout << "Validating fluid model for well " << getName() << "..." << m_useMass << std::endl; |
remove?
| std::cout << " Well: " << subRegion.getName() << " Est Attempt: " << dtAttempt | ||
| << ", ConfigurationIter: " << configurationLoopIter | ||
| << ", NewtonIter: " << newtonIter | ||
| << ", Residual Norm: " << residualNorm << std::endl; |
There was a problem hiding this comment.
This is inside a Newton iteration loop and will spam output every iteration.
Remove it? or guard by a log level?
| #include "fileIO/Outputs/OutputBase.hpp" | ||
| #include "physicsSolvers/fluidFlow/wells/WellFields.hpp" | ||
|
|
||
| #include "functions/FunctionManager.hpp" |
There was a problem hiding this comment.
| #include "functions/FunctionManager.hpp" |
remove this duplicate, as it has already been added in line 37
| setApplyDefaultValue( 0 ). | ||
| setInputFlag( InputFlags::OPTIONAL ). | ||
| setDescription( "Name of the BHP table when the rate is a time dependent function" ); | ||
| setDescription( "Flag to esitmate well solution prior to coupled reservoir and well solve." ); |
There was a problem hiding this comment.
| setDescription( "Flag to esitmate well solution prior to coupled reservoir and well solve." ); | |
| setDescription( "Flag to estimate well solution prior to coupled reservoir and well solve." ); |
| } | ||
| /// ViewKey struct for the WellControls class | ||
| viewKeysWellControls; | ||
| /// string key for the esitmate well solution flag |
There was a problem hiding this comment.
| /// string key for the esitmate well solution flag | |
| /// string key for the estimate well solution flag |
| @@ -345,8 +401,6 @@ | |||
| scale="0.1"/> | |||
| </FieldSpecifications> | |||
There was a problem hiding this comment.
| </FieldSpecifications> | |
| </FieldSpecifications> | |
| <!-- SPHINX_TUT_DEAD_OIL_EGG_FIELD_SPECS_END --> |
|
|
||
| <!-- SPHINX_TUT_DEAD_OIL_EGG_FIELD_SPECS_END --> | ||
| <!-- SPHINX_TUT_DEAD_OIL_EGG_OUTPUTS --> | ||
| <Outputs> |
There was a problem hiding this comment.
| <Outputs> | |
| <!-- SPHINX_TUT_DEAD_OIL_EGG_OUTPUTS --> | |
| <Outputs> |
| <Restart | ||
| name="restartOutput"/> | ||
|
|
||
| </Outputs> |
There was a problem hiding this comment.
| </Outputs> | |
| </Outputs> | |
| <!-- SPHINX_TUT_DEAD_OIL_EGG_OUTPUTS_END --> |
|
|
||
| <!-- SPHINX_TUT_DEAD_OIL_EGG_OUTPUTS_END --> | ||
| <!-- SPHINX_TUT_DEAD_OIL_EGG_TASKS --> | ||
| <Tasks> |
There was a problem hiding this comment.
| <Tasks> | |
| <!-- SPHINX_TUT_DEAD_OIL_EGG_TASKS --> | |
| <Tasks> |
| objectPath="ElementRegions/wellRegion4/wellRegion4UniqueSubRegion" | ||
| fieldName="wellElementMixtureConnectionRate"/> | ||
| fieldName="wellElementConnectionRate"/> | ||
| </Tasks> |
There was a problem hiding this comment.
| </Tasks> | |
| </Tasks> | |
| <!-- SPHINX_TUT_DEAD_OIL_EGG_TASKS_END --> |
jhuang2601
left a comment
There was a problem hiding this comment.
@tjb-ltk Great job!
Please update the branch with latest develop repo, which will fix the following failures for readthedoc build:
WARNING: Error, no command xref target from index:QuickStart
WARNING: Error, no command xref target from index:Tutorials
WARNING: Error, no command xref target from index:BasicExamples
WARNING: Error, no command xref target from index:AdvancedExamples
WARNING: Error, no command xref target from index:UserGuide
Replaces PR #3735 and extends PR #3971
Overview
This PR introduces
An improved well schema layout and code refactor better suited for well modeling. The previous implementation primarily targeted Jacobian generation requirements for the coupled reservoir and well system.
The well estimator is used to select the active well constraint by solving the well system assuming fixed reservoir conditions and selecting the constraint with the highest or lowest well flowing pressure.
This is a breaking change, detailed migration instructions and migration script are posted at #4081